package com.bluepunch.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bluepunch.entity.Category;
import com.bluepunch.entity.Comment;
import com.bluepunch.entity.DownloadGame;
import com.bluepunch.service.CategoryService;
import com.bluepunch.service.CommentService;
import com.bluepunch.service.DownloadGameService;
import com.bluepunch.utils.DownLoadUtils;
import com.bluepunch.vo.DownloadGameForm;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author bluepunch
 * @since 2023-10-08
 */
@Controller
//@RequestMapping("/game")
public class DownloadGameController {
    public static final Long TYPE = 1L;
    public static final String PATH = "templates/upload/game";
    @Autowired
    DownloadGameService gameService;
    @Autowired
    CategoryService categoryService;
    @Autowired
    CommentService commentService;

    @GetMapping("/game")
    public String gameList(Model model) {

        Page<DownloadGame> pageParam = new Page<>(1, 10);
        gameService.page(pageParam, new QueryWrapper<DownloadGame>().orderByDesc("create_time"));
        // 结果
        List<DownloadGame> gameList = pageParam.getRecords();
        model.addAttribute("gameList", gameList);
        model.addAttribute("pageParam", pageParam);


        // 分类信息
        List<Category> categoryList = categoryService.list(null);
        model.addAttribute("categoryList", categoryList);

        return "game/list";
    }

    @GetMapping("/game/{page}/{limit}")
    public String gameListPage(
            @PathVariable int page,
            @PathVariable int limit,
            Model model) {

        if (page < 1) {
            page = 1;
        }
        Page<DownloadGame> pageParam = new Page<>(page, limit);
        gameService.page(pageParam, new QueryWrapper<DownloadGame>().orderByDesc("create_time"));
        // 结果
        List<DownloadGame> gameList = pageParam.getRecords();
        model.addAttribute("gameList", gameList);
        model.addAttribute("pageParam", pageParam);

        // 分类信息
        List<Category> categoryList = categoryService.list(null);
        model.addAttribute("categoryList", categoryList);

        return "game/list";
    }

    // 跳转 发布游戏资源页
    @GetMapping("/game/write")
    public String toWrite(Model model) {
        List<Category> categoryList = categoryService.list(null);
        model.addAttribute("categoryList", categoryList);
        return "game/write";
    }

    @PostMapping("/game/write")
    public synchronized String write(DownloadGameForm gameForm, MultipartFile gameFile) {
        String ddesc = upload(gameFile);

        System.out.println("--------------------------------public synchronized String write(DownloadGameForm gameForm, MultipartFile gameFile)");
        System.out.println(gameForm);
        // 构建资源对象
        DownloadGame game = new DownloadGame();

        game.setDname(gameForm.getDname());
        game.setDdesc(ddesc);
        game.setDcode(gameForm.getDcode());
        game.setViews(0);

        game.setAuthorId("1");
        game.setAuthorName("ww");
        game.setAuthorAvatar("html1");

        Category category = categoryService.getById(gameForm.getCategoryId());
        game.setCategoryId(gameForm.getCategoryId());
        game.setCategoryName(category.getCategory());

        gameService.save(game);

        // 重定向到列表页面
        return "redirect:/game";
    }

    private String upload(MultipartFile attach) {
        if (!attach.isEmpty()) {

            // 获取源文件名称

            String fileName = attach.getOriginalFilename();

            // 获取源文件后缀名

            String suffix = FilenameUtils.getExtension(fileName);

            // 使用UUID重命名文件名称

            String newFileName = UUID.randomUUID().toString().replace("-", "") + (".") + suffix;

            // 使用日期解决同一文件夹中文件过多问题(以当前日期命名文件夹)

            String datePath = new SimpleDateFormat("yyyy-MM-dd").format(new Date());

            // 组装最终文件名

            String finalName = datePath + "/" + newFileName;

            // 构建文件对象

            File dest = new File(System.getProperty("user.dir"), PATH + "/" + finalName);//PATH + finalName
            // 判断该文件夹是否存在,不存在则创建

            System.out.println(dest.getAbsolutePath());
            if (!dest.getParentFile().exists()) {
                dest.getParentFile().mkdirs(); // 创建文件夹
            }
            try {
                System.out.println("--------------------------------------------------attach");
                System.out.println(attach.getOriginalFilename());
                // 将文件保存到硬盘
                attach.transferTo(dest);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return finalName;
        }
        return null;
    }

    // 浏览资源
    @GetMapping("/game/read/{id}")
    public String read(@PathVariable("id") String id, Model model) {
        DownloadGame game = gameService.getOne(new QueryWrapper<DownloadGame>().eq("id", id));
        // todo: redis缓存. 防止阅读重复
        game.setViews(game.getViews() + 1);
        gameService.updateById(game);

        String gameDown = game.getDname() + "." + game.getDdesc().split("\\.")[1];

        System.out.println("-----------------------gameDown");
        System.out.println(gameDown);

        model.addAttribute("gameDown", gameDown);
        model.addAttribute("game", game);
        // todo： 查询评论
        List<Comment> commentList = commentService.list(
                new QueryWrapper<Comment>().eq("parent_id", id).orderByDesc("create_time")
                        .eq("type", TYPE));
        model.addAttribute("commentList", commentList);
        return "game/read";
    }

    // 评论
    @PostMapping("/game/comment/{id}")
    public String comment(@PathVariable("id") Long id, Comment comment) {
        System.out.println("---------------------------------------------------------------------------");
        System.out.println(comment);
        // 存储评论
        comment.setType(TYPE);
        comment.setParentId(id);
        comment.setCreateTime(LocalDateTime.now());
        commentService.save(comment);
        // 重定向到列表页面
        return "redirect:/game/read/" + id;
    }

    /**
     * 下载文件
     *
     * @param response 响应
     * @param id       游戏资源id
     * @param dcode    提取码
     * @throws IOException
     */
    @GetMapping("/game/download/{id}")
    public void download(HttpServletRequest request, HttpServletResponse response,
                         @PathVariable("id") Long id, String dcode) throws IOException {

        DownloadGame game = gameService.getById(id);

        if (!game.getDcode().equals(dcode)) {
            response.sendError(201, "提取码错误");
            return;
        }

        //从服务器本地读取文件
        File file = new File(System.getProperty("user.dir"), PATH + "/" + game.getDdesc());
        //判断文件是否存在
        if (!file.exists()) {
            response.sendError(404, "你下载的资源不存在!!!");
        }
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
        //响应输出流
        OutputStream outputStream = response.getOutputStream();
        //设置响应头
        response.setHeader("content-type", "application/octet-stream");
        response.setContentType("application/octet-stream");
        response.setCharacterEncoding("UTF-8");
        //更改下载文件名
        String fileName = game.getDname() + "." + game.getDdesc().split("\\.")[1];
        String agent = request.getHeader("user-agent");
        String newName = DownLoadUtils.getFileName(agent, fileName);
        response.setHeader("Content-Disposition", "attachment;fileName=" + newName);
        //将文件以流的方式传给前端
        int i = 0;
        byte[] buff = new byte[1024];
        while ((i = bis.read(buff)) != -1) {
            outputStream.write(buff, 0, i);
        }
        bis.close();
        outputStream.close();
    }
}

